use std::net::SocketAddr;

use base_data::channel::EndReason;
use bytes::{Bytes, BytesMut};
use tools::{error::Error, ResultNull};

use crate::{
	empty_sockaddr,
	sip2::{
		head::{SipHeadField, CONTENT_LENGTH},
		utils::{fetch_number, trim_slice, WriteSip},
		SipDirection, SipMethod, SipResponse, CRLF,
	},
};

use super::LENGTH_ZERO;

#[derive(Debug)]
///sip的数据结构.
pub struct SipData {
	///存放完整的sip消息数据.有可能是收到的,也有可能是自己生成的
	pub(crate) data: Bytes,
	pub(crate) direction: SipDirection,
	pub(crate) title_name: Bytes,
	pub(crate) call_id: SipHeadField,
	pub(crate) from: SipHeadField,
	pub(crate) to: SipHeadField,
	pub(crate) via: SipHeadField,
	pub(crate) route: SipHeadField,
	pub(crate) record_route: SipHeadField,
	pub(crate) contact: SipHeadField,
	pub(crate) max_forwards: SipHeadField,
	pub(crate) content_length: SipHeadField,
	pub(crate) content_type: SipHeadField,
	pub(crate) supported: SipHeadField,
	pub(crate) allow: SipHeadField,
	pub(crate) allow_events: SipHeadField,
	pub(crate) expires: SipHeadField,
	pub(crate) cseq: SipHeadField,
	pub(crate) session_expires: SipHeadField,
	pub(crate) min_se: SipHeadField,
	pub(crate) p_asserted_identity: SipHeadField,
	pub(crate) p_early_media: SipHeadField,
	pub(crate) remote_party_id: SipHeadField,
	pub(crate) user_agent: SipHeadField,
	pub(crate) www_authenticate: SipHeadField,
	pub(crate) authorization: SipHeadField,
	pub(crate) require: SipHeadField,
	pub(crate) reason: SipHeadField,
	pub(crate) retry_after: SipHeadField,
	pub(crate) body: Bytes,
	///当前此次消息的对端ip
	pub(crate) peer_adder: SocketAddr,
}

impl Default for SipData {
	fn default() -> Self {
		Self {
			direction: SipDirection::Request(SipMethod::Unknown),
			title_name: Default::default(),
			call_id: Default::default(),
			from: Default::default(),
			to: Default::default(),
			via: Default::default(),
			route: Default::default(),
			record_route: Default::default(),
			contact: Default::default(),
			max_forwards: Default::default(),
			content_length: Default::default(),
			content_type: Default::default(),
			supported: Default::default(),
			allow: Default::default(),
			allow_events: Default::default(),
			expires: Default::default(),
			cseq: Default::default(),
			session_expires: Default::default(),
			min_se: Default::default(),
			p_asserted_identity: Default::default(),
			p_early_media: Default::default(),
			remote_party_id: Default::default(),
			user_agent: Default::default(),
			www_authenticate: Default::default(),
			authorization: Default::default(),
			require: Default::default(),
			reason: Default::default(),
			retry_after: Default::default(),
			body: Default::default(),
			peer_adder: empty_sockaddr(),
			data: Default::default(),
		}
	}
}

impl SipData {
	pub(crate) fn decode_transport_layer_packet(data: Bytes) -> Self {
		let mut sd = SipData::default();

		let mut index_start = 0;

		for i in 0..data.len() - 1 {
			match (&data[i..i + 2], index_start) {
				//找第一行.第一行是标题
				(CRLF, 0) => {
					sd.load_title(data.slice(0..i));
					index_start = i + 2;
				}
				(CRLF, _) => {
					//每一个行结束
					if i - index_start > 2 {
						sd.load_head(data.slice(index_start..i));
						index_start = i + 2;
					} else {
						//这个判断两个连接的结束符,做为头结束.后续完全就是body
						index_start = i + 2;
						sd.load_body(&data, index_start);

						break;
					}
				}
				_ => {
					//这里是没有找到结束.直接跳过就是
				}
			}
		}

		sd.data = data;

		sd
	}

	fn load_head(&mut self, b: Bytes) {
		let f = SipHeadField::from_bytes_line(b);
		match &f {
			SipHeadField::CallID(_) => self.call_id = f,
			SipHeadField::From(_) => self.from = f,
			SipHeadField::To(_) => self.to = f,
			SipHeadField::Via(_) => self.via = f,
			SipHeadField::Route(_) => self.route = f,
			SipHeadField::RecordRoute(_) => self.record_route = f,
			SipHeadField::Contact(_) => self.contact = f,
			SipHeadField::MaxForwards(_) => self.max_forwards = f,
			SipHeadField::ContentLength(_) => self.content_length = f,
			SipHeadField::ContentType(_) => self.content_type = f,
			SipHeadField::Supported(_) => self.supported = f,
			SipHeadField::Allow(_) => self.allow = f,
			SipHeadField::AllowEvents(_) => self.allow_events = f,
			SipHeadField::Expires(_) => self.expires = f,
			SipHeadField::CSeq(_) => self.cseq = f,
			SipHeadField::SessionExpires(_) => self.session_expires = f,
			SipHeadField::MinSE(_) => self.min_se = f,
			SipHeadField::PAssertedIdentity(_) => self.p_asserted_identity = f,
			SipHeadField::PEarlyMedia(_) => self.p_early_media = f,
			SipHeadField::RemotePartyID(_) => self.remote_party_id = f,
			SipHeadField::UserAgent(_) => self.user_agent = f,
			SipHeadField::WWWAuthenticate(_) => self.www_authenticate = f,
			SipHeadField::Authorization(_) => self.authorization = f,
			SipHeadField::Require(_) => self.require = f,
			SipHeadField::Reason(_) => self.reason = f,
			SipHeadField::RetryAfter(_) => self.retry_after = f,
			SipHeadField::Unknown => {}
		}
	}

	///读取body....
	///
	/// 无论任何协议,送到这里都应该是完整和独立的数据包
	/// 所以简单的不用根据什么长度,直接拿后面所有的数据
	/// 长度字段应该是用在确认是否完整上面
	#[inline]
	fn load_body(&mut self, buf: &Bytes, index: usize) {
		self.body = buf.slice(index..)
	}
	/// 解析SIP数据包的第一行,
	///
	/// 返回分别为第一行决定的方向,请求还是响应..请求的发起者数据..以及下一行开始的位置
	#[inline]
	fn load_title(&mut self, buf: Bytes) {
		let mut index = 0;
		let mut one = Bytes::new();
		let mut two = Bytes::new();

		for i in 0..buf.len() {
			//找到了分隔符
			match (buf[i], index) {
				(b' ', 0) => {
					one = buf.slice(0..i);
					index = i;
				}
				(b' ', _) => {
					two = trim_slice(&buf, index, i);
					break;
				}
				_ => {}
			}
		}

		if *one == *b"SIP/2.0" {
			self.direction = SipDirection::Response(two.as_ref().into());
		} else {
			self.direction = SipDirection::Request(one.as_ref().into());
			self.title_name = two;
		}
	}

	pub(crate) fn body<'a>(&'a self) -> &Bytes {
		&self.body
	}

	///针对一个sip数据包进行的初步验证过程..保证到达的数据完整性
	pub(crate) fn verify(&self) -> ResultNull {
		if self.call_id == SipHeadField::Unknown
			|| self.from == SipHeadField::Unknown
			|| self.to == SipHeadField::Unknown
			|| self.cseq == SipHeadField::Unknown
		{
			return Err(Error::InvalidData("sip包,没有必要的callid,from,to"));
		}

		Ok(())
	}

	///返回当前的sip是在一个对话中的,用来判断当前的sip消息是否应该存在对应的dialog
	/// true:在对话中
	pub(crate) fn is_in_dialog(&self) -> bool {
		match &self.direction {
			SipDirection::Request(m) => match m {
				crate::sip2::SipMethod::Invite => self.to.as_str().contains(";tag="),
				crate::sip2::SipMethod::Options
				| crate::sip2::SipMethod::Register
				| crate::sip2::SipMethod::Publish
				| crate::sip2::SipMethod::Notify => false,
				_ => true,
			},
			SipDirection::Response(_) => true,
		}
	}

	///因为当前返回结果未能生成dialog.所以不能使用dialog生成返回数据
	pub(crate) fn generate_call_not_exist(&self) -> Bytes {
		let mut buf = BytesMut::with_capacity(512);

		buf.put_sip_response(&SipResponse::DoesNotExist);
		buf.put_unbroken_head(&self.via);
		buf.put_unbroken_head(&self.call_id);
		buf.put_unbroken_head(&self.from);
		buf.put_unbroken_head(&self.to);
		buf.put_unbroken_head(&self.cseq);
		//单独写入长度
		buf.put_head_field(CONTENT_LENGTH, LENGTH_ZERO);
		buf.put_heads_end();

		buf.freeze()
	}

	///返回不支持的媒体类型
	pub(crate) fn generate_unsupported_media_type(&self) -> Bytes {
		let mut buf = BytesMut::with_capacity(512);

		buf.put_sip_response(&SipResponse::UnsupportedMediaType);
		buf.put_unbroken_head(&self.via);
		buf.put_unbroken_head(&self.call_id);
		buf.put_unbroken_head(&self.from);
		buf.put_unbroken_head(&self.to);
		buf.put_unbroken_head(&self.cseq);
		//单独写入长度
		buf.put_head_field(CONTENT_LENGTH, LENGTH_ZERO);
		buf.put_heads_end();

		buf.freeze()
	}

	///当前sip的呼入号码,先判定p-asserted-identity,没有再判定remote-party-id..然后再没有则从from中提取
	pub(crate) fn caller_num(&self) -> (Bytes, Bytes) {
		let b = self.p_asserted_identity.bytes();

		let b = if b.is_empty() {
			self.remote_party_id.bytes()
		} else {
			b
		};

		let b = if b.is_empty() {
			self.from.bytes()
		} else {
			b
		};

		fetch_number(b)
	}

	pub(crate) fn dest_num(&self) -> (Bytes, Bytes) {
		let b = self.to.bytes();
		fetch_number(b)
	}

	// ///返回当前的sip是在一个对话中的,
	// /// true:在对话中
	// pub(crate) fn is_in_dialog(&self) -> bool {
	// 	match &self.direction {
	// 		SipDirection::Request(m) => match m {
	// 			crate::sip2::SipMethod::Invite => {
	// 				if let Some(to_str) = self.load_str(SipHeadField::To) {
	// 					to_str.contains("tag=")
	// 				} else {
	// 					false
	// 				}
	// 			}
	// 			crate::sip2::SipMethod::Options
	// 			| crate::sip2::SipMethod::Register
	// 			| crate::sip2::SipMethod::Publish
	// 			| crate::sip2::SipMethod::Notify => false,
	// 			_ => true,
	// 		},
	// 		SipDirection::Response(_) => true,
	// 	}
	// }

	// #[inline]
	// fn load_str(&self, head_name: SipHeadField) -> Option<&str> {
	// 	for item in &self.heads {
	// 		if item.0 == head_name {
	// 			return Some(get_str(&self.data, item.1.clone()));
	// 		}
	// 	}
	// 	None
	// }

	// #[inline]
	// pub(crate) fn get_title_u8<'a>(&'a self) -> &'a [u8] {
	// 	self.get_u8(self.title_name.clone())
	// }

	// #[inline]
	// pub(crate) fn get_u8<'a>(&'a self, range: Range<usize>) -> &'a [u8] {
	// 	if self.data.len() < range.end {
	// 		error!("{:?}获取数据范围超出.{}", self, range.end);
	// 		&self.data[0..0]
	// 	} else {
	// 		&self.data[range]
	// 	}
	// }

	// // pub(crate) fn c_seq_method(&self) -> SipMethod {
	// // 	let r = first_range_by_bytes(&self.heads, SipHeadField::CSeq);
	// // 	if !r.is_empty() {
	// // 		let rs = positioning_character(&self.data, r.start, b' ');
	// // 		get_str(&self.data, &((rs.end + 1)..r.end)).into()
	// // 	} else {
	// // 		SipMethod::Unknown
	// // 	}
	// // }

	pub fn to_hangup_reason(&self) -> EndReason {
		match self.direction {
			SipDirection::Response(r) => match r.into() {
				100..=299 => EndReason::UnknownValue,
				300..=399 => EndReason::Transfer,
				400..=499 => EndReason::CalledHangup(self.reason.as_str().to_owned()),
				500..=599 => EndReason::ServerInternalError,
				600..=699 => EndReason::UnknownValue,
				_ => EndReason::UnknownValue,
			},
			_ => EndReason::UnknownValue,
		}
	}

	pub(crate) fn generate_ok(&self) -> Bytes {
		let mut buf = BytesMut::with_capacity(1024);

		buf.put_sip_response(&SipResponse::Ok);
		buf.put_unbroken_head(&self.via);
		buf.put_unbroken_head(&self.from);
		buf.put_unbroken_head(&self.to);
		buf.put_unbroken_head(&self.cseq);
		buf.put_head_field(CONTENT_LENGTH, LENGTH_ZERO);
		buf.put_heads_end();

		buf.freeze()
	}
}
